﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Text;

namespace Dot5Demo
{
    /// <summary>
    ///文本对齐
    /// </summary>
    public class DTTextAlignment
    {
        private StringAlignment _alignment = StringAlignment.Near;
        private StringBuilder _cachedBuilder = null;
        private int _colSpaceCount = 5;

        private string _endFlag = string.Empty;

        private Font _font;

        private float _spaceWidth = -1;

        private string _startFlag = string.Empty;

        private DataTable DataTable;

        private Graphics graphics = null;

        /// <summary>
        /// 使用空格分隔
        /// </summary>
        private char space = ' ';

        public StringAlignment Alignment
        {
            get { return _alignment; }
            set
            {
                if (_alignment != value)
                    ClearCache();
                _alignment = value;
            }
        }

        /// <summary>
        /// 列间距多少个空格
        /// </summary>
        public int ColSpaceCount
        {
            get
            {
                return _colSpaceCount;
            }
            set
            {
                if (_colSpaceCount != value)
                    ClearCache();
                _colSpaceCount = value;
            }
        }
        /// <summary>
        /// 数据的结束符号
        /// </summary>
        public string EndFlag
        {
            get
            {
                return _endFlag;
            }
            set
            {
                if (_endFlag != value)
                    ClearCache();
                _endFlag = value;
            }
        }
        public Font Font
        {
            get { return _font; }
            set
            {
                if (!_font.Equals(value))
                    ClearCache();
                _font = value;
            }
        }

        /// <summary>
        /// 数据的开始符号
        /// </summary>
        public string StartFlag
        {
            get
            {
                return _startFlag;
            }
            set
            {
                if (_startFlag != value)
                    ClearCache();
                _startFlag = value;
            }
        }

        private float SpaceWidth
        {
            get
            {
                {
                    if (_spaceWidth == -1)
                        _spaceWidth = GetTextLength(new string(space, 20) + '-') - GetTextLength(new string(space, 19) + '-');
                    return _spaceWidth;
                }
            }
        }

        public DTTextAlignment(Graphics g, Font font)
        {
            graphics = g;
            _font = font;
            //两个空格长度减去一个空格长度，才是一个空格占用的真正长度
            _spaceWidth = GetTextLength(new string(space, 41) + '-') - GetTextLength(new string(space, 40) + '-');
            //不同的字符串的空格长度都有差异
            var tt = GetTextLength(" ");
            var t0 = GetTextLength(new string(space, 2) + '-') - GetTextLength(new string(space, 1) + '-');
            var t1 = GetTextLength(new string(space, 10) + '-') - GetTextLength(new string(space, 9) + '-');
            var t2 = GetTextLength(new string(space, 20) + '-') - GetTextLength(new string(space, 19) + '-');
            var t3 = GetTextLength(new string(space, 40) + '-') - GetTextLength(new string(space, 39) + '-');
        }

        public void SetDataSource(DataTable table)
        {
            ClearCache();
            DataTable = table;
        }

        /// <summary>
        /// 生成结果
        /// </summary>
        /// <returns></returns>
        public string[] GetResultArray()
        {
            var colWidths = MaxColWidths;
            List<string> resultList = new List<string>();
            for (int i = 0; i < DataTable.Rows.Count; i++)
            {
                StringBuilder sbLine = new StringBuilder();
                float k = 0;
                for (int c = 0; c < DataTable.Columns.Count; c++)
                {
                    StringBuilder sb = new StringBuilder();
                    //当前Cell
                    string data = StartFlag + DataTable.Rows[i][c].ToString() + EndFlag;
                    //计算应该使用多少个空格来填充
                    k += colWidths[c] + ColSpaceCount * _spaceWidth;
                    int spaceCount = (int)((k - GetTextLength(sbLine.ToString() + data)) / _spaceWidth);
                    //对齐方式
                    switch (Alignment)
                    {
                        case StringAlignment.Near:
                            sb.Append(data + new string(space, spaceCount));
                            break;

                        case StringAlignment.Far:
                            sb.Append(new string(space, spaceCount) + data);
                            break;

                        case StringAlignment.Center:
                            int every = (int)(spaceCount / 2);
                            sb.Append(new string(space, every) + data + new string(space, every));
                            if (spaceCount % 2 == 1)
                            {
                                sb.Append(space);
                            }
                            break;

                        default:
                            break;
                    }
                    sbLine.Append(sb);
                }
                resultList.Add(sbLine.ToString());
            }
            return resultList.ToArray();
        }

        public string GetResultString()
        {
            if (_cachedBuilder != null)
                return _cachedBuilder.ToString();
            var builder = new StringBuilder();
            var res = GetResultArray();
            for (int i = 0; i < res.Length; i++)
            {
                builder.AppendLine(res[i]);
            }
            _cachedBuilder = builder;
            return builder.ToString();
        }

        private void ClearCache()
        {
            _cachedBuilder = null;
            _maxColWidths = null;
        }

        private float[] _maxColWidths = null;
        private float[] MaxColWidths
        {
            get
            {
                if (_maxColWidths == null)
                    CalcMaxColoWidth();
                return _maxColWidths;
            }
        }

        private void CalcMaxColoWidth()
        {
            var temp = new float[DataTable.Columns.Count];
            for (int r = 0; r < DataTable.Rows.Count; r++)
            {
                for (int c = 0; c < DataTable.Columns.Count; c++)
                {
                    string data = StartFlag + DataTable.Rows[r][c].ToString() + EndFlag;
                    float f = GetTextLength(data);
                    if (f > temp[c])
                        temp[c] = f + 2.0f;
                }
            }
            _maxColWidths = temp;
        }

        private float GetTextLength(string text)
        {
            SizeF sizeF = graphics.MeasureString(text, _font);
            return sizeF.Width;
        }
    }
}